package com.dhecp.project.flowable.controller;

import com.alibaba.fastjson.JSON;
import com.dhecp.common.annotation.RepeatSubmit;
import com.dhecp.common.core.controller.BaseController;
import com.dhecp.common.core.domain.AjaxResult;
import com.dhecp.common.core.page.TableDataInfo;
import com.dhecp.common.utils.MessageUtils;
import com.dhecp.common.utils.StringUtils;
import com.dhecp.framework.util.ShiroUtils;
import com.dhecp.project.flowable.domain.ActHistoricTask;
import com.dhecp.project.flowable.domain.ActRuntimeTask;
import com.dhecp.project.flowable.domain.ActSimpleActivity;
import com.dhecp.project.flowable.domain.SysProcessInstance;
import com.dhecp.project.flowable.extend.FlowableUtils;
import com.dhecp.project.flowable.service.ActProcessTaskService;
import com.dhecp.project.system.domain.SysUserInfoSimple;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName ActProcessTaskController
 * @Description 任务控制器
 * @Author alula
 * @Date 2020-06-30 10:29
 */
@Controller
@RequestMapping("/flowable/task")
public class ActProcessTaskController extends BaseController {

    @Autowired
    private ActProcessTaskService actProcessTaskService;

    //待办任务数据
    @RequestMapping("/todoTaskList")
    @ResponseBody
    public TableDataInfo todoTaskList(@RequestParam Map<String, Object> params) {
        startPage();
        List<ActRuntimeTask> list = actProcessTaskService.queryTodoActRuntimeTask(params);
        return getDataTable(list);
    }

    //已办任务数据
    @RequestMapping("/doneTaskList")
    @ResponseBody
    public TableDataInfo doneTaskList(@RequestParam Map<String, Object> params) {
        startPage();
        List<ActHistoricTask> list = actProcessTaskService.queryDoneActHistoricTask(params);
        return getDataTable(list);
    }

    //任务通过处理页面
    @RequestMapping("/taskPass")
    @ResponseBody
    public AjaxResult taskPass(@RequestParam("nid") String nid,
                               @RequestParam("jumpUrl") String jumpUrl) {
        String nextTaskId = "";
        SysProcessInstance sysProcessInstance = actProcessTaskService.querySysProcessInstanceByTableDataId(nid);
        if (sysProcessInstance == null){
            return  AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        nextTaskId = sysProcessInstance.getNextTaskId();
        FlowElement curActivity = actProcessTaskService.queryActivitiImplByProDefIdandActId(sysProcessInstance.getProcDefId(), sysProcessInstance.getNextActId());
        if(curActivity != null){
            String curActType = FlowableUtils.getFlowElementType(curActivity);
            //对于多实例（会签）互斥网关环节与并行网关环节时，要去取真实的任务ID，不用sysProcessInstance对象中的getNextTaskId值，因为会签/并行网关环节会有多任务，getNextTaskId只是其中一个任务ID不对
            if ("parallelGateway".contains(curActType) || actProcessTaskService.isMultiInstance(curActivity) || actProcessTaskService.isParallelGatewayInnerUserTask(sysProcessInstance.getProcDefId(), curActivity.getId())) {
                Task multiTask = actProcessTaskService.queryUserCurrentInstanceRunTask(sysProcessInstance.getProcInstId(), ShiroUtils.getMandatorId());
                if (multiTask != null){
                    nextTaskId = multiTask.getId();
                }
            }
        }
        Task task = actProcessTaskService.queryTaskById(nextTaskId);
        if (task == null){
            return  AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (task.isSuspended() == true){
            return  AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
        }
        int taskCount = actProcessTaskService.queryUserCurrentInstanceRunTaskCount(task.getProcessInstanceId(), ShiroUtils.getMandatorId());
        if (taskCount == 0){
            return  AjaxResult.error(MessageUtils.message("flowable.task.error.taskruncountzero"));
        }
        ProcessInstance processInstance = actProcessTaskService.queryProcessInstanceByInstId(task.getProcessInstanceId());
        if (processInstance == null){
            return  AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        FlowElement nextActivity = actProcessTaskService.queryCurrentTaskNextActivity(nextTaskId);
        String activityType = "userTask";
        boolean activityMulti = false;
        boolean isParallelGatewayInnerUserTask = false;
        if (nextActivity != null){
            activityType = FlowableUtils.getFlowElementType(nextActivity);
            isParallelGatewayInnerUserTask = actProcessTaskService.isParallelGatewayInnerUserTask(task.getProcessDefinitionId(), nextActivity.getId());
            //对于多实例（会签）互斥网关环节与并行网关环节时，activityMulti为true，不允许删除列表用户
            if ("parallelGateway".contains(activityType) || actProcessTaskService.isMultiInstance(nextActivity) || isParallelGatewayInnerUserTask == true) {
                activityMulti = true;
            }
        }
        boolean isSameAct = curActivity.getId().contains(nextActivity.getId());
        List<SysUserInfoSimple> userInfoList = actProcessTaskService.queryNextTaskCandidateUsers(task.getProcessDefinitionId(), task.getId(), nextActivity, isParallelGatewayInnerUserTask);
        Map<String, Object> mapList = new HashMap<>();
        mapList.put("taskId", nextTaskId);
        mapList.put("taskName", task.getName());
        mapList.put("taskPriority", task.getPriority());
        mapList.put("procInstId", processInstance.getId());
        mapList.put("procDefId", processInstance.getProcessDefinitionId());
        mapList.put("processTitle", sysProcessInstance.getProcessTitle());
        mapList.put("tableDataId", sysProcessInstance.getTableDataId());
        mapList.put("jumpUrl", jumpUrl);
        mapList.put("activityType", activityType);
        mapList.put("activityMulti", activityMulti);
        mapList.put("userInfoList", JSON.toJSON(userInfoList));
        AjaxResult ajaxResult = AjaxResult.success(mapList);
        return  ajaxResult;
    }

    //任务通过POST
    @RequestMapping("/taskPassPost")
    @ResponseBody
    public AjaxResult taskPassPost(@RequestParam String taskId,
                                   @RequestParam Integer priority,
                                   @RequestParam(required = false) List<String> assignees,
                                   @RequestParam(required = false) String comment,
                                   @RequestParam(required = false) String medium) {
        AjaxResult ajaxResult = new AjaxResult();
        try {
            ajaxResult = actProcessTaskService.passProcess(taskId, priority, comment, assignees, null, medium, "app");
            return ajaxResult;
        }
        catch (Exception e) {
            return AjaxResult.error(this.getExceptionMessage(e));
        }
    }

    //任务回退处理页面
    @RequestMapping("/taskBack")
    @ResponseBody
    public AjaxResult taskBack(@RequestParam("nid") String nid,
                                 @RequestParam("jumpUrl") String jumpUrl) {
        String nextTaskId = "";
        SysProcessInstance sysProcessInstance = actProcessTaskService.querySysProcessInstanceByTableDataId(nid);
        if (sysProcessInstance == null){
            return  AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        nextTaskId = sysProcessInstance.getNextTaskId();
        FlowElement curActivity = actProcessTaskService.queryActivitiImplByProDefIdandActId(sysProcessInstance.getProcDefId(), sysProcessInstance.getNextActId());
        if(curActivity != null){
            String curActType = FlowableUtils.getFlowElementType(curActivity);
            //对于多实例（会签）互斥网关环节与并行网关环节时，要去取真实的任务ID，不用sysProcessInstance对象中的getNextTaskId值，因为会签/并行网关环节会有多任务，getNextTaskId只是其中一个任务ID不对
            if ("parallelGateway".contains(curActType) || actProcessTaskService.isMultiInstance(curActivity) || actProcessTaskService.isParallelGatewayInnerUserTask(sysProcessInstance.getProcDefId(), curActivity.getId())) {
                Task multiTask = actProcessTaskService.queryUserCurrentInstanceRunTask(sysProcessInstance.getProcInstId(), ShiroUtils.getMandatorId());
                if (multiTask != null){
                    nextTaskId = multiTask.getId();
                }
            }
        }
        Task task = actProcessTaskService.queryTaskById(nextTaskId);
        if (task == null){
            return  AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (task.isSuspended() == true){
            return  AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
        }
        int taskCount = actProcessTaskService.queryUserCurrentInstanceRunTaskCount(task.getProcessInstanceId(), ShiroUtils.getMandatorId());
        if (taskCount == 0){
            return  AjaxResult.error(MessageUtils.message("flowable.task.error.taskruncountzero"));
        }
        ProcessInstance processInstance = actProcessTaskService.queryProcessInstanceByInstId(task.getProcessInstanceId());
        if (processInstance == null){
            return  AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        FlowElement prevActivity = actProcessTaskService.queryCurrentTaskPrevActivity(nextTaskId, task.getTaskDefinitionKey());
        String activityType = "userTask";
        boolean activityMulti = false;
        if (prevActivity != null){
            activityType = FlowableUtils.getFlowElementType(prevActivity);
            //对于多实例（会签）互斥网关环节与并行网关环节时，activityMulti为true，不允许删除列表用户(isMultiInstance 判断多人会签)
            if ("parallelGateway".contains(activityType) || actProcessTaskService.isMultiInstance(prevActivity)) {
                activityMulti = true;
            }
        }
        List<SysUserInfoSimple> userInfoList = actProcessTaskService.queryPrevTaskCandidateUsers(sysProcessInstance.getProcInstId(), prevActivity);
        Map<String, Object> mapList = new HashMap<>();
        mapList.put("taskId", nextTaskId);
        mapList.put("taskName", task.getName());
        mapList.put("taskPriority", task.getPriority());
        mapList.put("procInstId", processInstance.getId());
        mapList.put("procDefId", processInstance.getProcessDefinitionId());
        mapList.put("processTitle", sysProcessInstance.getProcessTitle());
        mapList.put("tableDataId", sysProcessInstance.getTableDataId());
        mapList.put("jumpUrl", jumpUrl);
        mapList.put("activityType", activityType);
        mapList.put("activityMulti", activityMulti);
        mapList.put("userInfoList", JSON.toJSON(userInfoList));
        AjaxResult ajaxResult = AjaxResult.success(mapList);
        return  ajaxResult;
    }

    //任务回退POST
    @RequestMapping("/taskBackPost")
    @ResponseBody
    public AjaxResult taskBackPost(@RequestParam String taskId,
                                   @RequestParam Integer priority,
                                   @RequestParam(required = false) List<String> assignees,
                                   @RequestParam(required = false) String comment,
                                   @RequestParam(required = false) String medium) {
        AjaxResult ajaxResult = new AjaxResult();
        try {
            ajaxResult = actProcessTaskService.backProcess(taskId, priority, comment, assignees, null, medium, "app");
            return ajaxResult;
        }
        catch (Exception e) {
            return AjaxResult.error(this.getExceptionMessage(e));
        }
    }

    //任务重置回退处理页面
    @RequestMapping("/taskRestBack")
    @ResponseBody
    public AjaxResult taskRestBack(@RequestParam("nid") String nid,
                                   @RequestParam("jumpUrl") String jumpUrl) {
        String nextTaskId = "";
        SysProcessInstance sysProcessInstance = actProcessTaskService.querySysProcessInstanceByTableDataId(nid);
        if (sysProcessInstance == null){
            return  AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        FlowElement prevActivity = actProcessTaskService.queryActivitiImplByProDefIdandActId(sysProcessInstance.getProcDefId(), sysProcessInstance.getPrevActId());
        List<SysUserInfoSimple> userInfoList = null;
        if(prevActivity != null) {
            userInfoList = actProcessTaskService.queryPrevTaskCandidateUsers(sysProcessInstance.getProcInstId(), prevActivity);
        }
        Map<String, Object> mapList = new HashMap<>();
        mapList.put("taskPriority", 1);
        mapList.put("procInstId", sysProcessInstance.getProcInstId());
        mapList.put("procDefId", sysProcessInstance.getProcDefId());
        mapList.put("processTitle", sysProcessInstance.getProcessTitle());
        mapList.put("tableDataId", sysProcessInstance.getTableDataId());
        mapList.put("jumpUrl", jumpUrl);
        mapList.put("activityId", prevActivity.getId());
        mapList.put("userInfoList", JSON.toJSON(userInfoList));
        AjaxResult ajaxResult = AjaxResult.success(mapList);
        return  ajaxResult;
    }

    //任务重置回退POST
    @RequestMapping("/taskRestBackPost")
    @ResponseBody
    public AjaxResult taskRestBackPost(@RequestParam String nid,
                                       @RequestParam String activityId,
                                       @RequestParam Integer priority,
                                       @RequestParam(required = false) List<String> assignees,
                                       @RequestParam(required = false) String comment,
                                       @RequestParam(required = false) String medium) {
        AjaxResult ajaxResult = new AjaxResult();
        try {
            ajaxResult = actProcessTaskService.resetBackProcess(nid, activityId,priority, comment, assignees, medium, "app");
            return ajaxResult;
        }
        catch (Exception e) {
            return AjaxResult.error(this.getExceptionMessage(e));
        }
    }

    //任务驳回处理页面
    @RequestMapping("/taskReject")
    @ResponseBody
    public AjaxResult taskReject(@RequestParam("nid") String nid, @RequestParam("jumpUrl") String jumpUrl) {
        String nextTaskId = "";
        SysProcessInstance sysProcessInstance = actProcessTaskService.querySysProcessInstanceByTableDataId(nid);
        if (sysProcessInstance == null){
            return  AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        nextTaskId = sysProcessInstance.getNextTaskId();
        FlowElement curActivity = actProcessTaskService.queryActivitiImplByProDefIdandActId(sysProcessInstance.getProcDefId(), sysProcessInstance.getNextActId());
        if(curActivity != null){
            String curActType = FlowableUtils.getFlowElementType(curActivity);
            //对于多实例（会签）互斥网关环节与并行网关环节时，要去取真实的任务ID，不用sysProcessInstance对象中的getNextTaskId值，因为会签/并行网关环节会有多任务，getNextTaskId只是其中一个任务ID不对
            if ("parallelGateway".contains(curActType) || actProcessTaskService.isMultiInstance(curActivity) || actProcessTaskService.isParallelGatewayInnerUserTask(sysProcessInstance.getProcDefId(), curActivity.getId())) {
                Task multiTask = actProcessTaskService.queryUserCurrentInstanceRunTask(sysProcessInstance.getProcInstId(), ShiroUtils.getMandatorId());
                if (multiTask != null){
                    nextTaskId = multiTask.getId();
                }
            }
        }
        Task task = actProcessTaskService.queryTaskById(nextTaskId);
        if (task == null){
            return  AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        if (task.isSuspended() == true){
            return  AjaxResult.error(MessageUtils.message("flowable.process.error.suspendedfail"));
        }
        ProcessInstance processInstance = actProcessTaskService.queryProcessInstanceByInstId(task.getProcessInstanceId());
        if (processInstance == null){
            return  AjaxResult.error(MessageUtils.message("flowable.process.error.instanceobjectfail"));
        }
        List<ActSimpleActivity> activityList = actProcessTaskService.queryRejectActivityList(task.getProcessDefinitionId(), task.getProcessInstanceId(), task.getId(), task.getTaskDefinitionKey());
        Map<String, Object> mapList = new HashMap<>();
        mapList.put("taskId", nextTaskId);
        mapList.put("taskName", task.getName());
        mapList.put("taskPriority", task.getPriority());
        mapList.put("procInstId", processInstance.getId());
        mapList.put("procDefId", processInstance.getProcessDefinitionId());
        mapList.put("processTitle", sysProcessInstance.getProcessTitle());
        mapList.put("tableDataId", sysProcessInstance.getTableDataId());
        mapList.put("jumpUrl", jumpUrl);
        mapList.put("activityList", JSON.toJSON(activityList));
        AjaxResult ajaxResult = AjaxResult.success(mapList);
        return  ajaxResult;
    }

    //任务驳回POST
    @RequestMapping("/taskRejectPost")
    @ResponseBody
    public AjaxResult taskRejectPost(@RequestParam String taskId,
                                     @RequestParam String activityId,
                                     @RequestParam Integer priority,
                                     @RequestParam(required = false) List<String> assignees,
                                     @RequestParam(required = false) String comment,
                                     @RequestParam(required = false) String medium) {
        AjaxResult ajaxResult = new AjaxResult();
        try {
            ajaxResult = actProcessTaskService.rejectProcess(taskId, activityId,priority, comment, assignees, null, medium, "app");
            return ajaxResult;
        }
        catch (Exception e) {
            return AjaxResult.error(this.getExceptionMessage(e));
        }
    }

    //获取驳回环节用户列表
    @RequestMapping("/getRejectActUser")
    @ResponseBody
    public AjaxResult getRejectActUser(@RequestParam String taskId,
                                       @RequestParam String activityId){
        AjaxResult ajaxResult = new AjaxResult();
        if(StringUtils.isEmpty(taskId)){
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "taskId"));
        }
        if(StringUtils.isEmpty(activityId)){
            return AjaxResult.error(MessageUtils.message("module.error.paramnotempty", "activityId"));
        }
        Task task = actProcessTaskService.queryTaskById(taskId);
        if(task == null){
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskobjectfail"));
        }
        FlowElement activity = actProcessTaskService.queryActivitiImplByProDefIdandActId(task.getProcessDefinitionId(), activityId);
        if(activity == null){
            return AjaxResult.error(MessageUtils.message("flowable.task.error.taskactivityfail"));
        }
        List<SysUserInfoSimple> userInfoList = actProcessTaskService.queryPrevTaskCandidateUsers(task.getProcessInstanceId(), activity);
        return new AjaxResult(AjaxResult.Type.SUCCESS, MessageUtils.message("module.success.issuccess"), userInfoList);
    }

    //判断驳回条件是否成立
    @RequestMapping("/judgeRejectCond")
    @ResponseBody
    public AjaxResult judgeRejectCond(@RequestParam String activityId){
        AjaxResult ajaxResult = new AjaxResult();
        if("flowzd".equals(activityId.toLowerCase())) {
            ajaxResult = AjaxResult.warn(MessageUtils.message("module.warn.isflowzd"));
        }else{
            ajaxResult = AjaxResult.success(MessageUtils.message("module.success.issuccess"));
        }
        return ajaxResult;
    }

    @RepeatSubmit
    @RequestMapping("/taskDelegatePost")
    @ResponseBody
    public AjaxResult taskDelegatePost(@RequestParam String taskId,
                                       @RequestParam String userId,
                                       @RequestParam(required = false) String comment) {
        AjaxResult ajaxResult = new AjaxResult();
        try {
            ajaxResult = actProcessTaskService.delegateProcess(taskId, userId, comment);
            return ajaxResult;
        }
        catch (Exception e) {
            return AjaxResult.error(this.getExceptionMessage(e));
        }
    }

    //批量PASS任务
    @RepeatSubmit
    @RequestMapping("/taskPassAllPost")
    @ResponseBody
    public AjaxResult taskPassAllPost(@RequestParam String[] taskIds,
                                      @RequestParam Integer priority,
                                      @RequestParam(required = false) String comment,
                                      @RequestParam(required = false) String medium) {
        AjaxResult ajaxResult = new AjaxResult();
        try {
            ajaxResult = actProcessTaskService.passAllProcess(taskIds, priority, comment, medium);
            return ajaxResult;
        }
        catch (Exception e) {
            return AjaxResult.error(this.getExceptionMessage(e));
        }
    }

    //批量回退任务
    @RepeatSubmit
    @RequestMapping("/taskBackAllPost")
    @ResponseBody
    public AjaxResult taskBackAllPost(@RequestParam String[] taskIds,
                                      @RequestParam Integer priority,
                                      @RequestParam(required = false) String comment,
                                      @RequestParam(required = false) String medium) {
        AjaxResult ajaxResult = new AjaxResult();
        try {
            ajaxResult = actProcessTaskService.backAllProcess(taskIds, priority, comment, medium);
            return ajaxResult;
        }
        catch (Exception e) {
            return AjaxResult.error(this.getExceptionMessage(e));
        }
    }

    @RequestMapping("/getUserTodoTaskCount")
    @ResponseBody
    public long getUserTodoRunTaskCount(){
        long count = 0;
        try {
            count = actProcessTaskService.queryCurrentUserTodoActRuntimeTaskCount(1);
        }
        catch (Exception e) {
        }
        return count;
    }
}
